# -*- coding: utf-8 -*-
import urllib.request,urllib.parse, json, datetime, time
from weibo import APIClient
from openpyxl.workbook import Workbook
from openpyxl.writer.excel import ExcelWriter 

APP_KEY = '1643430974' # app key
APP_SECRET = 'de18126d65bbbca2b957092ab749f599' # app secret
TOKEN='2.00jJ9L3BMTfNnBa6e18c55d3S6aGxD'
EXPIRE_TIME=0x711FFFFF

client = APIClient(app_key=APP_KEY, app_secret=APP_SECRET)
client.set_access_token(TOKEN, EXPIRE_TIME)



		

#def get_json_dicted(url,unlimit=False):
#	"""从api的url返回json页面的str类型"""
#	jsonpage = urllib.request.urlopen(url)
#	jsonpage_bytes = jsonpage.read()
#	jsonpage_str = jsonpage_bytes.decode("utf8")
#	jsondict=json.loads(jsonpage_str)
#	jsonpage.close()
#	return jsondict



def get_systime_now():
	"""获取当前系统时间"""
	return datetime.datetime.ctime(datetime.datetime.today())

def timecontrol():
	j=client.account.rate_limit_status.get()
	t=[j['remaining_user_hits'],j['reset_time_in_seconds']]
	if t[0]==0:
		print('Limit reached!! You have to wait for %d sec for countinue'%(t[1]))
		for i in int(t[1]/10):
			t[1]+=-10
			time.sleep(10)
			print('You have to still wait for %d'%(t[1]))
		print('it will countinue in 10 seconds')
		time.sleep(10)
		j=client.account.rate_limit_status.get()
	return j['remaining_user_hits']

		

def get_burden_count(count,base):
	if isinstance(count,int) and isinstance(base,int):
		pass
	else:
		raise TypeError('You should put two int type here')

	if count%base==0:
		return int(count/base)
	else:
		return int(count/base)+1

def alphabate(i,s):
	"""
	字母生成器,生成xlcx列用
	i是需要转换的数字
	s是输入的初始字符
	"""
	if i>25:
		s+=chr(int(i%26)+65)
		return alphabate(int(i/26)-1,s)
	else:
		s+=chr(int(i%26)+65)
		return s[::-1]

def gen_dict2xlcx_col(keys,keys2=None):
	"""生成字典属性将要输入xlcx文件的列"""
	dict_keys={}
	if not isinstance(keys, tuple):
		raise TypeError('You should put a tuple here')


	if keys2!=None:
		if not isinstance(keys, tuple):
			raise TypeError('You should put a tuple here')
		for i in range(len(keys),len(keys2)+len(keys)):
			dict_keys[keys2[i-len(keys)]]=alphabate(i,'')
		return dict_keys


	for i in range(len(keys)):
		dict_keys[keys[i]]=alphabate(i,'')
	return dict_keys


		


def api_user_timeline(userid,page=1,count=100):
	"""user_timeline的API调用借口"""
	return client.statuses.user_timeline.get(uid=userid,page=page,count=count)
#	api_url="https://api.weibo.com/2/statuses/user_timeline.json"
#
#	url=api_url+"?uid=%s&page=%d&count=%d" % (str(userid),page,count)
#
#	if need_token==True:
#		url+="&access_token=%s" % (token)
#	return url

def api_user_show(para,is_id=True):
	"""user_show的API调用借口"""
	if is_id:
		return client.users.show.get(uid=para)
	return client.users.show.get(screen_name=para)

#	api_url="https://api.weibo.com/2/users/show.json"
#	if is_id:
#		url=api_url+"?uid="+str(para)
#	else:
#		url=api_url+"?screen_name="+str(para)
#
#	if need_token:
#		url+="&access_token="+token
#
#	return url



#print (apiurl_user_timeline())
#print(get_jsonpage_str(apiurl_user_timeline()))
#data=json.loads(get_jsonpage_str(apiurl_user_timeline(1989412233)))
#print(type(data['statuses'][0]))

class User(dict):
	"""docstring for User"""
	user_keys=('id','idstr','screen_name','name','province','city','location','description','url','profile_image_url',
			'profile_url','domain','weihao','gender','followers_count','friends_count','statuses_count','favourites_count',
			'created_at','allow_all_act_msg','geo_enabled','verified','verified_type','allow_all_comment','avatar_large',
			'verified_reason','bi_followers_count','lang')
	user_sp_keys=()		#返回不一定有的键值
	user_m_keys=('followers_burden','friends_burden','bi_followers_burden','status_burden','fetched_at')

	user_xldict=gen_dict2xlcx_col(user_keys+user_sp_keys+user_m_keys)		#生成xlcx列对应项的字典

	def __init__(self, data, output=False):
		
		if not isinstance(data, dict):
			raise TypeError('Initial Parameter should be a dict')

		try:
			for i in self.__class__.user_keys:
				exec('self[\'%s\']=data[\'%s\']'%(i,i))		#按照user_key中的键值读取data中的内容。
		except KeyError as e:
			raise KeyError(e)

		self['followers_burden']=get_burden_count(self['followers_count'],200)
		self['friends_burden']=get_burden_count(self['friends_count'],200)
		self['bi_followers_burden']=get_burden_count(self['bi_followers_count'],200)
		self['status_burden']=get_burden_count(self['statuses_count'],100)
		self['fetched_at']=get_systime_now()	
				

		if output:
			self.outputform()
	
	def outputform(self):
		try:
			for i in self.__class__.user_xldict:
				self[self.__class__.user_xldict[i]]=self.pop(i)
		except KeyError:
			raise ValueError('It\'s not normal form of User class')

	def normalform(self):
		try:
			for i in self.__class__.user_xldict:
				self[i]=self.pop(self.__class__.user_xldict[i])
		except KeyError:
			raise ValueError('It\'s not output form of User class')


class Weibo(dict):
	"""dict，从已结构化的字典数据定义至微博类型,v0.1"""
	weibo_keys=('created_at','id','mid','idstr','text','source','favorited','truncated','geo','user','reposts_count','comments_count',
		'attitudes_count')
	weibo_sp_keys=('thumbnail_pic','bmiddle_pic','original_pic',)	#不一定有的键值
	weibo_m_keys=('origin','fetched_at','retweeted_status')
	
	keys=weibo_keys+weibo_sp_keys+weibo_m_keys

	weibo_xldict=gen_dict2xlcx_col(keys)
	

	def __init__(self,data,output=False):
		if not isinstance(data, dict):
			raise TypeError('Initial Parameter should be a dict')

		try:
			for i in self.__class__.weibo_keys:
				if i=='user':
					self['user']=User(data['user']).__str__()
				else:
					exec('self[\'%s\']=data[\'%s\']'%(i,i))  #按照weibo_keys中的各项对data进行读取，并赋予属性
		except KeyError as e:
			raise KeyError(e)

		for i in self.__class__.weibo_sp_keys:
			try:
				exec('self[\'%s\']=data[\'%s\']'%(i,i))  #按照weibo_keys中的各项对data进行读取，并赋予属性，如果找不到Key则赋值为-1
			except KeyError as e:
				#print(e)
				exec('self[\'%s\']=-1'%(i))

		try:
			self['retweeted_status']=ReWeibo(data['retweeted_status']).__str__()	#Weibo		尝试读取转发微博来源，没有则留空
			self['origin']=False
		except KeyError as e:
			self['retweeted_status']=-1
			self['origin']=True

		self['fetched_at']=get_systime_now()	#string		摘录时间


		if output:
			self.outputform()
	

	def outputform(self):
		try:
			for i in self.__class__.weibo_xldict:
				self[self.__class__.weibo_xldict[i]]=self.pop(i)
		except KeyError as e:

			raise ValueError(e)

	def normalform(self):
		try:
			for i in self.__class__.weibo_xldict:
				self[i]=self.pop(self.__class__.weibo_xldict[i])
		except KeyError:
			raise ValueError('It\'s not output form of Weibo class')

class ReWeibo(Weibo):
	reWeibo_keys=[]
	for i in Weibo.keys:
		reWeibo_keys.append('re_'+i)
	reweibo_xldict=gen_dict2xlcx_col(Weibo.keys,reWeibo_keys)

	def outputform(self):
		try:
			for i in self.__class__.reweibo_xldict:
				self[self.__class__.reweibo_xldict[i]]=self.pop(i)
		except KeyError as e:

			raise ValueError(e)

	def normalform(self):
		try:
			for i in self.__class__.reweibo_xldict:
				self[i]=self.pop(self.__class__.reweibo_xldict[i])
		except KeyError:
			raise ValueError('It\'s not output form of Weibo class')
		
class Comment(dict):
	"""docstring for Comment"""
	def __init__(self, data,output=False):
		comment_keys=('created_at','id','text','source','user','mid','idstr','status','reply_comment')
		comment_sp_keys=()
		comment_m_keys=('fetched_at')

		comment_xldict=gen_dict2xlcx_col(comment_keys+comment_sp_keys+comment_m_keys)

		if isinstance(data, dict):
			raise TypeError('Initial Parameter should be a dict')

		try:
			for i in comment_keys:
				if i=='status':
					self['status']=Weibo(data['status'])
				elif i=='user':
					self['user']=User(data['user'])
				else:
					exec('self[\'%s\']=data[\'%s\']'%(i,i))		#按照comment_key中的键值读取data中的内容。
		except KeyError as e:
			raise KeyError(e)

		self['fetched_at']=get_systime_now()	
				

		if output:
			self.outputform()

	def outputform(self):
		try:
			for i in self.__class__.comment_xldict:
				self[self.__class__.comment_xldict[i]]=self.pop(i)
		except KeyError:
			raise ValueError('It\'s not normal form of Comment class')

	def normalform(self):
		try:
			for i in self.__class__.comment_xldict:
				self[i]=self.pop(self.__class__.comment_xldict[i])
		except KeyError:
			raise ValueError('It\'s not output form of Comment class')


#def fetch_user(para,is_id=True):
#	"""根据用户名或用户ID查询用户，默认ID，用户名查询时is_id应False"""
#	para=urllib.parse.quote(para,encoding='utf-8')		#转换为utf8传递
#	return User(get_json_dicted(apiurl_user_show(para,is_id)))

def user_timeline(para, is_id):
	hits=timecontrol()
	wb=Workbook()
	dest_filename = r'user_statuses.xlsx'
	ws = wb.worksheets[0]

	user=User(api_user_show(para,is_id),False)
	ws.title = user['screen_name']
	index= {v:k for k, v in Weibo.weibo_xldict.items()}
	ws.append(index)
	if user['status_burden']>hits:
		print('Warning! You may have to wait.')
	for i in range(1,user['status_burden']+1):
		s=api_user_timeline(user['id'],i,100)
		for j in s['statuses']:
			ws.append(Weibo(j,True))

	wb.save(filename = dest_filename)